﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Acms.Bll.Tests
{
    public static class AssertHelper
    {
        internal static void AreEqual(System.Data.Linq.Binary expected, byte[] actual)
        {
            AreEqual(expected.ToArray(), actual, null);
        }

        internal static void AreEqual(byte[] actual, System.Data.Linq.Binary expected)
        {
            AreEqual(expected.ToArray(), actual, null);
        }

        public static void AreEqual(byte[] expected, byte[] actual)
        {
            AreEqual(expected, actual, null);
        }

        public static void AreEqual(byte[] expected, byte[] actual, string message)
        {
            if (expected == null)
            {
                Assert.IsNull(actual, message);
            }
            else
            {
                Assert.IsNotNull(actual, message);
                Assert.AreEqual(expected.Length, actual.Length, string.Concat(message, " - Element Length"));
                int i = 0;
                foreach(var item in expected)
                {
                    Assert.AreEqual(item, actual[i], string.Concat(message, " - Element ", i));
                    i++;
                }
            }
        }

        public static void AreEqual(DateTime? expected, DateTime? actual)
        {
            AreEqual(expected, actual, false, null);
        }

        public static void AreEqual(DateTime? expected, DateTime? actual, bool checkMiliseconds)
        {
            AreEqual(expected, actual, checkMiliseconds, null);
        }

        public static void AreEqual(DateTime? expected, DateTime? actual, string message)
        {
            AreEqual(expected, actual, false, message);
        }

        public static void AreEqual(DateTime? expected, DateTime? actual, bool checkMiliseconds, string message)
        {
            if (expected == null)
            {
                Assert.IsNull(actual, message);
            }
            else
            {
                Assert.IsNotNull(actual, message);
                if (checkMiliseconds)
                {
                    Assert.AreEqual(expected.Value, actual.Value, string.Concat(message, " : miliseconds included {0} vs {1}", expected.Value.Millisecond, actual.Value.Millisecond));
                }
                else
                {
                    Assert.AreEqual(
                        new DateTime(expected.Value.Year, expected.Value.Month, expected.Value.Day, expected.Value.Hour, expected.Value.Minute, expected.Value.Second, 0)
                        , new DateTime(actual.Value.Year, actual.Value.Month, actual.Value.Day, actual.Value.Hour, actual.Value.Minute, actual.Value.Second, 0)
                        , message + ": miliseconds not included");
                }
            }
        }

        public static void AreEqual(DateTime expected, DateTime actual, int millisecondsDifference)
        {
            var timeSpan = actual - expected;
            Assert.IsTrue(timeSpan.Milliseconds < millisecondsDifference, string.Format("Dates '{0:dd/MM/yyyy HH:mm:ss mmm}' and '{1:dd/MM/yyyy HH:mm:ss mmm}' expected a difference of less than {2} miliseconds but was {3}", expected, actual, millisecondsDifference, timeSpan.Milliseconds));
        }

        public static DateTime? ToLocalTime(this DateTime? source)
        {
            if (source != null)
            {
                return new DateTime?(DateTime.SpecifyKind(source.Value, DateTimeKind.Utc).ToLocalTime());
            }
            else
            {
                return null;
            }
        }

        public static DateTime? ToUniversalTime(this DateTime? source)
        {
            if (source != null)
            {
                return new DateTime?(DateTime.SpecifyKind(source.Value, DateTimeKind.Local).ToUniversalTime());
            }
            else
            {
                return null;
            }
        }

    }
}
